#include "Carte.hpp"

using namespace std;
using namespace sf;

Carte::Carte()
{
    //ctor
        nbTerr = 0;
        territoires = NULL;
        grilleSelection = NULL;
        centres = NULL;

        tD.loadFromFile(QApplication::applicationDirPath().toStdString() + "/de.png");
        sD.setTexture(tD);
}

void Carte::setNbTerr(int nbTerr)
{
    this->nbTerr=nbTerr;
}

int Carte::getNbTerr() const
{
    return nbTerr;
}

void Carte::setTab( int t)
{
        if(centres)
        {
                delete []centres;
        }
        this->centres = new sf::Vector2i[t];
}

void Carte::setCentre(int indice,const sf::Vector2i& v)
{
    this->centres[indice]=v;
}

sf::Vector2i* Carte::getCentres()
{
        return centres;
}

const sf::Vector2i& Carte::getCentre(int indice) const
{
    return this->centres[indice];
}

void Carte::genererCarte(int nbJ,int nbTerrpJ)
{
    nbTerr=(nbJ*nbTerrpJ);

        cout << "NbJ:" << nbJ << " - nbTPJ:" << nbTerrpJ << endl;

//      cout << "CARTE :" << endl << endl << endl;
//      cout << "***********************" << endl << nbTerr << endl;

    ///Creation de la grille d'hexagones

    Hexagone hTab[TAB_LENGTH][TAB_HEIGHT];

    for(int j(0);j<TAB_HEIGHT;j++)
    {
        if(j%2==0)
        {
            for(int i(0);i<TAB_LENGTH;i++)
            {
                hTab[i][j]=Hexagone((i*H_LENGTH)+MARGE_LEFT,(j*((H_HEIGHT/4)*3))+MARGE_TOP);  /// Attention !
            }
        }
        else
        {
            for(int i(0);i<TAB_LENGTH;i++)
            {
                hTab[i][j]=Hexagone(((i*H_LENGTH)+(H_LENGTH/2))+MARGE_LEFT,((j*((H_HEIGHT/4)*3)))+MARGE_TOP);  /// Attention !
            }
        }
    }

//      cout << "fin creer hexa" << endl;
    ///Choix aleatoires des centres de territoire

    setTab(nbTerr);

        srand(time(NULL));

    for(int i(0);i<nbTerr;i++)
    {
        int a(0);
        Vector2i v((rand()%TAB_LENGTH),(rand()%TAB_HEIGHT));
        while(a<i)
        {
            float fx((hTab[v.x][v.y].getPoint(0).x)-(hTab[centres[a].x][centres[a].y].getPoint(0).x)),fy((hTab[v.x][v.y].getPoint(0).y)-(hTab[centres[a].x][centres[a].y].getPoint(0).y));
            if(((fx*fx)+(fy*fy))<PORTEE)
            {
                a=0;
                v.x=rand()%TAB_LENGTH;
                v.y=rand()%TAB_HEIGHT;
            }
            else
            {
                a++;
            }
        }
        centres[i]=v;
    }

//      cout << "fin alea" << endl;
    ///Completion des territoires

    territoires=new Territoire*[nbTerr];

    for (int i(0);i<nbTerr;i++)
    {
        territoires[i]=new Territoire();
        territoires[i]->setIndice(i);
    }

    vector<Hexagone> restes[nbTerr];

//      cout << "heheheee" << endl;

    for(int j(0);j<TAB_HEIGHT;j++)
    {
        for(int i(0);i<TAB_LENGTH;i++)
        {
            int a(-1);
            float dist(PORTEE);

            for(int k(0);k<nbTerr;k++)
            {
                float fx((hTab[i][j].getPoint(0).x)-(hTab[centres[k].x][centres[k].y].getPoint(0).x)),fy((hTab[i][j].getPoint(0).y)-(hTab[centres[k].x][centres[k].y].getPoint(0).y));
                float temp((fx*fx)+(fy*fy));
                if(temp<dist)
                {
                    dist=temp;
                    a=k;
                }
            }

            if(a>=0)
            {
                if (territoires[a]->getFrontiere().getPointCount()==0)
                {
                    territoires[a]->setFrontiere(hTab[i][j]);
                }
                else
                {
                    territoires[a]->ajouterHexagone(hTab[i][j],restes[a]);
                }
                territoires[a]->setSurface(hTab[i][j]);
            }
        }
    }

//      cout << "else" << endl;

    for (int i(0);i<nbTerr;i++)
    {
        int taille(restes[i].size());
        for (int j(0);j<taille;j++)
        {
            Hexagone h(restes[i].back());
            restes[i].pop_back();
            territoires[i]->ajouterHexagone(h,restes[i]);
        }
    }

    ///Activation des frontieres

    for (int i(0);i<nbTerr;i++)
    {
        territoires[i]->setOutline();
        territoires[i]->setOutlineColor(false);
    }

    ///Determination des territoires voisins de chaque territoire

    int lg((TAB_LENGTH*2)+2),hg((TAB_HEIGHT*3)+2);

    vector<int>** grilleVoisins;

    grilleVoisins=new vector<int>*[lg];
    for (int i(0);i<lg;i++)
    {
        grilleVoisins[i]=new vector<int>[hg];
    }

    bool bilanVoisins[nbTerr][nbTerr];

    for (int i(0);i<nbTerr;i++)
    {
        int nbPoints(territoires[i]->getFrontiere().getPointCount());
        for (int k(0);k<nbPoints;k++)
        {
            grilleVoisins[((int(territoires[i]->getFrontiere().getPoint(k).x))-MARGE_LEFT)/10][((int(territoires[i]->getFrontiere().getPoint(k).y))-MARGE_TOP)/5].push_back(i);
        }
    }

    for (int i(0);i<nbTerr;i++)
    {
        for (int j(0);j<nbTerr;j++)
        {
            bilanVoisins[i][j]=false;
        }
    }

//      cout << "prout" << endl;

    for (int i(0);i<nbTerr;i++)
    {
        int nbPoints(territoires[i]->getFrontiere().getPointCount());
        for (int k(0);k<nbPoints;k++)
        {
            vector<int> vv(grilleVoisins[((int(territoires[i]->getFrontiere().getPoint(k).x))-MARGE_LEFT)/10][((int(territoires[i]->getFrontiere().getPoint(k).y))-MARGE_TOP)/5]);
            int taille(vv.size());
            for (int l(0);l<taille;l++)
            {
                int a(vv[l]);
                if (i!=a)
                {
                    bilanVoisins[i][a]=true;
                }
            }
        }
    }

//      cout << "bientot" << endl;

    for (int i(0);i<nbTerr;i++)
    {
        for (int j(0);j<nbTerr;j++)
        {
            if (bilanVoisins[i][j])
            {
                territoires[i]->setVoisin(j);
            }
        }
    }

//      cout << "mystere" << endl;

        if(grilleVoisins)
        {
        for (int i(0);i<lg;i++)
        {
                        if(grilleVoisins[i])
                        {
                delete[] grilleVoisins[i];
                                grilleVoisins[i] = NULL;
                        }
        }
        delete[] grilleVoisins;
                grilleVoisins = NULL;
        }

//      cout << "ouhou" << endl;

    //textureCarte.create(800,600);

//      cout << "finnn!!!!!!" << endl;
}


void Carte::genererCarteClient(int nbJ,int nbTerrpJ)
{
    nbTerr=(nbJ*nbTerrpJ);

    ///Creation de la grille d'hexagones

    Hexagone hTab[TAB_LENGTH][TAB_HEIGHT];

    for(int j(0);j<TAB_HEIGHT;j++)
    {
        if(j%2==0)
        {
            for(int i(0);i<TAB_LENGTH;i++)
            {
                hTab[i][j]=Hexagone((i*H_LENGTH)+MARGE_LEFT,(j*((H_HEIGHT/4)*3))+MARGE_TOP);  /// Attention !
            }
        }
        else
        {
            for(int i(0);i<TAB_LENGTH;i++)
            {
                hTab[i][j]=Hexagone(((i*H_LENGTH)+(H_LENGTH/2))+MARGE_LEFT,((j*((H_HEIGHT/4)*3)))+MARGE_TOP);  /// Attention !
            }
        }
    }

    ///Completion des territoires

    territoires=new Territoire*[nbTerr];

    for (int i(0);i<nbTerr;i++)
    {
        territoires[i]=new Territoire();
        territoires[i]->setIndice(i);
    }

    vector<Hexagone> restes[nbTerr];

    for(int j(0);j<TAB_HEIGHT;j++)
    {
        for(int i(0);i<TAB_LENGTH;i++)
        {
            int a(-1);
            float dist(PORTEE);

            for(int k(0);k<nbTerr;k++)
            {
                float fx((hTab[i][j].getPoint(0).x)-(hTab[centres[k].x][centres[k].y].getPoint(0).x)),fy((hTab[i][j].getPoint(0).y)-(hTab[centres[k].x][centres[k].y].getPoint(0).y));
                float temp((fx*fx)+(fy*fy));
                if(temp<dist)
                {
                    dist=temp;
                    a=k;
                }
            }

            if(a>=0)
            {
                if (territoires[a]->getFrontiere().getPointCount()==0)
                {
                    territoires[a]->setFrontiere(hTab[i][j]);
                }
                else
                {
                    territoires[a]->ajouterHexagone(hTab[i][j],restes[a]);
                }
                territoires[a]->setSurface(hTab[i][j]);
            }
        }
    }
    for (int i(0);i<nbTerr;i++)
    {
        int taille(restes[i].size());
        for (int j(0);j<taille;j++)
        {
            Hexagone h(restes[i].back());
            restes[i].pop_back();
            territoires[i]->ajouterHexagone(h,restes[i]);
        }
    }

    ///Activation des frontieres

    for (int i(0);i<nbTerr;i++)
    {
        territoires[i]->setOutline();
        territoires[i]->setOutlineColor(false);
    }

    ///Determination des territoires voisins de chaque territoire

    int lg((TAB_LENGTH*2)+2),hg((TAB_HEIGHT*3)+2);

    vector<int>** grilleVoisins;

    grilleVoisins=new vector<int>*[lg];
    for (int i(0);i<lg;i++)
    {
        grilleVoisins[i]=new vector<int>[hg];
    }

    bool bilanVoisins[nbTerr][nbTerr];

    for (int i(0);i<nbTerr;i++)
    {
        int nbPoints(territoires[i]->getFrontiere().getPointCount());
        for (int k(0);k<nbPoints;k++)
        {
            grilleVoisins[((int(territoires[i]->getFrontiere().getPoint(k).x))-MARGE_LEFT)/10][((int(territoires[i]->getFrontiere().getPoint(k).y))-MARGE_TOP)/5].push_back(i);
        }
    }

    for (int i(0);i<nbTerr;i++)
    {
        for (int j(0);j<nbTerr;j++)
        {
            bilanVoisins[i][j]=false;
        }
    }

    for (int i(0);i<nbTerr;i++)
    {
        int nbPoints(territoires[i]->getFrontiere().getPointCount());
        for (int k(0);k<nbPoints;k++)
        {
            vector<int> vv(grilleVoisins[((int(territoires[i]->getFrontiere().getPoint(k).x))-MARGE_LEFT)/10][((int(territoires[i]->getFrontiere().getPoint(k).y))-MARGE_TOP)/5]);
            int taille(vv.size());
            for (int l(0);l<taille;l++)
            {
                int a(vv[l]);
                if (i!=a)
                {
                    bilanVoisins[i][a]=true;
                }
            }
        }
    }

    for (int i(0);i<nbTerr;i++)
    {
        for (int j(0);j<nbTerr;j++)
        {
            if (bilanVoisins[i][j])
            {
                territoires[i]->setVoisin(j);
            }
        }
    }

    for (int i(0);i<lg;i++)
    {
        delete[] grilleVoisins[i];
                grilleVoisins[i] = NULL;
    }
    delete[] grilleVoisins;
        grilleVoisins = NULL;

    textureCarte.create(800,600);
    textureDes.create(800, 600);
}



bool Carte::composante() const
{
    bool dejaVu[nbTerr];

    for (int i(0);i<nbTerr;i++)
    {
        dejaVu[i]=false;
    }
    dejaVu[0]=true;

    this->auxComposante(dejaVu,0);

    bool resultat(true);

    for (int i(1);i<nbTerr;i++)
    {
        resultat=(resultat&&dejaVu[i]);
    }
    return resultat;
}

void Carte::repartirTerritoires(int nbJ,int nbTerrpJ,Camp camps[])
{
    //cout << territoires[0]->getIndice() << endl;
    for (int i(0);i<nbJ;i++)
    {
        for (int j(0);j<nbTerrpJ;j++)
        {
            camps[i].ajouterTerritoire(territoires[(i*nbTerrpJ)+j]);
            //territoires[(i*nbTerrpJ)+j]->setIndiceCamp(i);
        }
    }
}

void Carte::updateTexture(Sprite& cibleCarte, Sprite& cibleDes)
{
    textureCarte.clear(Color::White);

    for (int i(0);i<nbTerr;i++)
    {
        territoires[i]->dessiner(textureCarte);
    }
    textureCarte.display();

    cibleCarte.setTexture(textureCarte.getTexture());

    textureDes.clear(Color::Transparent);

    for (int i(0);i<nbTerr;i++)
    {
        Vector2f point1(territoires[i]->getFrontiere().getPoint(0)), point2(territoires[i]->getFrontiere().getPoint((territoires[i]->getFrontiere().getPointCount())/2));
        float baseX(((point1.x + point2.x)/2)-widthD), baseY(((point1.y+point2.y)/2)-heightD);
        int nb(territoires[i]->getNbDesCourant());
        /*
        stringstream ss;
        ss << i << endl;
        Text t(ss.str());
        t.setPosition(baseX,baseY);
        textureDes.draw(t);
        */
        for(int j(0); j < nb; j++)
        {
            sf::Color c;
            int r(Camp::Couleurs[territoires[i]->getIndiceCamp()].r + 75);
            int g(Camp::Couleurs[territoires[i]->getIndiceCamp()].g + 75);
            int b(Camp::Couleurs[territoires[i]->getIndiceCamp()].b + 75);

            if (r > 255) { r = 255; }
            if (g > 255) { g = 255; }
            if (b > 255) { b = 255; }

            c.r = r;
            c.g = g;
            c.b = b;

            int col(j/4), ligne(j%4);
            sD.setPosition(col*widthD + baseX, 0 - ligne*heightD + baseY + decalBas*col);
            sD.setColor(c);

            textureDes.draw(sD);
            //std::cout << "i = " << i << " - j = " << j << " - col = " << col << " - baseX = " << baseX  << " - ligne = " << ligne << " - baseY = " << baseY << std::endl;
        }
    }
    textureDes.display();

    cibleDes.setTexture(textureDes.getTexture());
}

void Carte::creerGrilleSelection()
{
    int lg((TAB_LENGTH*2)+2),hg((TAB_HEIGHT*3)+2);

    grilleSelection=new Vector3i*[lg];
    for (int i(0);i<lg;i++)
    {
        grilleSelection[i]=new Vector3i[hg];
    }

    for (int i(0);i<(TAB_LENGTH*2+1);i++)
    {
        for (int j(0);j<(TAB_HEIGHT*3+1);j++)
        {
            grilleSelection[i][j].x=-1;
            grilleSelection[i][j].y=-1;
            grilleSelection[i][j].z=-1;
        }
    }

    for (int i(0);i<nbTerr;i++)
    {
        int taille(territoires[i]->getNbHexagones());
        for (int j(0);j<taille;j++)
        {
            int xGrille((((territoires[i]->getSurface(j).getPoint(0).x)-10)-MARGE_LEFT)/10);
            int yGrille(((territoires[i]->getSurface(j).getPoint(0).y)-MARGE_TOP)/5);

            grilleSelection[xGrille][yGrille].x=2;
            grilleSelection[xGrille][yGrille].z=i;

            grilleSelection[xGrille+1][yGrille].x=1;
            grilleSelection[xGrille+1][yGrille].y=i;

            for (int k(0);k<2;k++)
            {
                for (int l(0);l<2;l++)
                {
                    grilleSelection[xGrille+l][yGrille+k+1].x=0;
                    grilleSelection[xGrille+l][yGrille+k+1].y=i;
                }
            }

            grilleSelection[xGrille][yGrille+3].x=1;
            grilleSelection[xGrille][yGrille+3].z=i;

            grilleSelection[xGrille+1][yGrille+3].x=2;
            grilleSelection[xGrille+1][yGrille+3].y=i;
        }
    }
}

void Carte::selectionnerTerritoire(int positionX,int positionY,int& indiceSelection) const
{
    if ((positionX >= MARGE_LEFT)&&(positionX < (MARGE_LEFT+(TAB_LENGTH*H_LENGTH)+10))&&(positionY >= MARGE_TOP)&&(positionY < (MARGE_TOP+(TAB_HEIGHT*(H_HEIGHT/4*3))+5)))
    {
        Vector3i v(grilleSelection[((positionX)-MARGE_LEFT)/10][((positionY)-MARGE_TOP)/5]);

        if (v.x==0)
        {
            indiceSelection=v.y;
        }
        if (v.x==1)
        {
            if ((((positionX)-MARGE_LEFT)%10)<((((positionY)-MARGE_TOP)%5)*2))
            {
                if (v.y>-1)
                {
                    indiceSelection=v.y;
                }
            }
            else
            {
                if (v.z>-1)
                {
                    indiceSelection=v.z;
                }
            }
        }
        if (v.x==2)
        {
            if ((((positionX)-MARGE_LEFT)%10)<(10-((((positionY)-MARGE_TOP)%5)*2)))
            {
                if (v.y>-1)
                {
                    indiceSelection=v.y;
                }
            }
            else
            {
                if (v.z>-1)
                {
                    indiceSelection=v.z;
                }
            }
        }
    }
}


void Carte::clear()
{
        //cout << getNbTerr() << " T " << endl;

        if(territoires)
        {
                for (int i(0);i<getNbTerr();i++)
        {
                   if(territoires[i])
                   {
                    delete territoires[i];
                                territoires[i] = NULL;
                   }
        }

                cout << "out" << endl;

                delete[] territoires;
                territoires = NULL;
        }

}



Carte::~Carte()
{
    //dtor

  if(grilleSelection)
  {
    for (int i(0);i<((TAB_LENGTH*2)+2);i++)
    {
                if(grilleSelection[i])
                { delete grilleSelection[i]; grilleSelection[i] = NULL; }
    }
    delete[] grilleSelection;
        grilleSelection = NULL;
  }

        clear();

}

void Carte::auxComposante(bool tab[],int indice) const
{
    int taille(territoires[indice]->getNbVoisins());

    for (int i(0);i<taille;i++)
    {
        int indiceVoisin(territoires[indice]->getVoisin(i));
        if (!tab[indiceVoisin])
        {
            tab[indiceVoisin]=true;
            this->auxComposante(tab,indiceVoisin);
        }
    }
}
